package top.codecrab.lock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写锁测试
 *
 * @author codecrab
 * @since 2021年06月30日 16:56
 */
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache cache = new MyCache();

        for (int i = 1; i <= 5; i++) {
            int finalI = i;
            new Thread(() -> {
                cache.set(String.valueOf(finalI), finalI);
            }, String.valueOf(i)).start();
        }

        for (int i = 1; i <= 5; i++) {
            int finalI = i;
            new Thread(() -> {
                Object o = cache.get(String.valueOf(finalI));
            }, String.valueOf(i)).start();
        }
    }
}

/**
 * 加上读写锁
 */
class MyCache {
    private volatile Map<String, Object> cache = new HashMap<>();
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    public void set(String key, Object value) {
        rwLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "\t正在进行写操作：" + value);
            TimeUnit.MILLISECONDS.sleep(500);
            cache.put(key, value);
            System.out.println(Thread.currentThread().getName() + "\t写操作完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rwLock.writeLock().unlock();
        }
    }

    public Object get(String key) {
        rwLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "\t正在进行读操作");
            TimeUnit.MILLISECONDS.sleep(500);
            Object res = cache.get(key);
            System.out.println(Thread.currentThread().getName() + "\t读操作完成：" + res);
            return res;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            rwLock.readLock().unlock();
        }
    }
}

/*
class MyCache {
    //未上读写锁
    private static volatile Map<String, Object> cache = new HashMap<>();

    public void set(String key, Object value) {
        System.out.println(Thread.currentThread().getName() + "\t正在进行写操作：" + value);
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        cache.put(key, value);
        System.out.println(Thread.currentThread().getName() + "\t写操作完成");
    }

    public Object get(String key) {
        System.out.println(Thread.currentThread().getName() + "\t正在进行读操作");
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Object res = cache.get(key);
        System.out.println(Thread.currentThread().getName() + "\t读操作完成：" + res);
        return res;
    }

    public void clear() {
        cache.clear();
    }
}
*/
